﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.IO;
using System.Xml.Serialization;

namespace KTVConsole2.Core
{
    public class Song : ICloneable
    {
        public string SongName { get; set; }
        public string Star { get; set; }
        public string Path { get; set; }
        public int Duration { get; set; }
        public string SongNamePinYin { get; set; }
        public string SongNameJianPin { get; set; }
        public string StarPinYin { get; set; }
        public string StarJianPin { get; set; }
        public int AudioCount { get; set; }
        /// <summary>
        /// 0: full
        /// 1: left
        /// 2: right
        /// </summary>
        public int CurrentAudioLeftOrRight { get; set; }

        /// <summary>
        /// 歌曲点播的ID。歌曲在PLAYLIST中的唯一标识
        /// </summary>
        public int Id { get; set; }
        public override string ToString()
        {
            return SongName;
        }

        /// <summary>
        /// 根据SongName进行排序
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public int CompareTo(object obj)
        {
            Song song = obj as Song;
            return this.SongName.CompareTo(song.SongName);
        }


        public object Clone()
        {
            return base.MemberwiseClone();
        }
    }




    public class FavoriteSongs
    {
        public string Title { get; set; }
        private ObservableCollection<Song> songs = new ObservableCollection<Song>();
        public ObservableCollection<Song> Songs { get { return songs; } set { songs = value; } }
    }

    //public class SongsPlayedManager
    //{
    //    private ObservableCollection<SongPlayed> allSongsPlayed = new ObservableCollection<SongPlayed>();
    //    public ObservableCollection<SongPlayed> AllSongsPlayed { get; }
    //}

    //public class SongPlayed
    //{
    //    private DateTime playedDate;
    //    private ObservableCollection<Song> song = new ObservableCollection<Song>();
    //    public DateTime PlayedDate{
    //}

    public class SongPlayedManager
    {
        #region 构造函数
        private SongPlayedManager()
        {
            allFavoriteSongs = new ObservableCollection<SongPlayed>();
        }

        /// <summary>
        /// 从xml文件中读取历史列表
        /// 注意之前请先给XmlFilePath属性赋值。否则将使用默认值获取列表
        /// </summary>
        /// <returns>实例</returns>
        public static SongPlayedManager GetInstance()
        {
            if (File.Exists(XmlFilePath))
                return Util.Util.XmlDeserialize<SongPlayedManager>(XmlFilePath);
            else
                return new SongPlayedManager();
        }

        /// <summary>
        /// 从xml文件中读取历史列表
        /// </summary>
        /// <param name="xmlFilePath">文件路径</param>
        /// <returns>实例</returns>
        public static SongPlayedManager GetInstance(string xmlFilePath)
        {
            XmlFilePath = xmlFilePath;
            return GetInstance();
        }
        #endregion

        #region 公共属性及常量
        public static string XmlFilePath = "songplayed.xml";

        public ObservableCollection<SongPlayed> AllFavoriteSongs
        {
            get { return allFavoriteSongs; }
            set { allFavoriteSongs = value; }
        }
        #endregion

        #region 公共方法        
        /// <summary>
        /// 在历史列表中增加一首歌
        /// </summary>
        /// <param name="song">歌曲</param>
        public void AddSong(Song song)
        {
            //看看歌曲是否存在
            //如果存在，则fre+1
            //如果不存，则fre = 1
            SongPlayed sp = FindSongPlayed(song);
            if (sp == null)
            {
                sp = new SongPlayed();
                sp.Frequency = 1;
                sp.Song = song.Clone() as Song;
                allFavoriteSongs.Add(sp);
            }
            else
            {
                sp.Frequency++;
            }
            
        }

        /// <summary>
        /// 删除选定的历史歌曲
        /// </summary>
        /// <param name="song2"></param>
        public void DeleteSong(SongPlayed songToDelete)
        {
            allFavoriteSongs.Remove(songToDelete);
        }

        /// <summary>
        /// 统计，最受欢迎的歌曲
        /// </summary>
        /// <returns></returns>
        public ObservableCollection<SongPlayed> GetAll()
        {
            return allFavoriteSongs;
        }

        /// <summary>
        /// 可以统计，最受欢迎的歌手，按被点的总次数排列，然后选择歌手后，再按受欢迎程度，显示歌曲列表
        /// </summary>
        /// <returns>歌手列表（用SongPlayed的结构存储）</returns>
        public ObservableCollection<SongPlayed> GetFavoriteStars()
        {
            var stars = from b in
                            (from a in allFavoriteSongs
                             group a by a.Song.Star into g
                             select new SongPlayed { Frequency = g.Sum(p => p.Frequency), Song = g.First().Song })
                        orderby b.Frequency descending
                        select b;
            return new ObservableCollection<SongPlayed>(stars);
        }

        /// <summary>
        /// 获取选定歌手唱过的歌曲。按歌曲受欢迎程度排列
        /// </summary>
        /// <param name="favoriteStars">歌手</param>
        /// <returns>歌曲列表</returns>
        public ObservableCollection<SongPlayed> GetSongsOfFavoriteStar(SongPlayed favoriteStar)
        {
            var sr = from a in allFavoriteSongs where a.Song.Star == favoriteStar.Song.Star orderby a.Frequency descending select a;
            return new ObservableCollection<SongPlayed>(sr);
        }

        /// <summary>
        /// 保存到xml文件。注意提前给xmlFilePath赋值。
        /// </summary>
        public void SaveToXml()
        {
            XmlSerializer ser = new XmlSerializer(this.GetType());
            string path = XmlFilePath;
            using (Stream s = File.Open(path, System.IO.FileMode.Create, System.IO.FileAccess.Write))
            {
                try
                {
                    ser.Serialize(s, this);
                }
                catch (Exception e)
                {
                    s.Close();
                    try
                    {
                        File.Delete(path);
                    }
                    catch (IOException) { }
                    Util.Util.TellUser(e.Message);
                }
            }
        }
        #endregion

        #region 私有字段
        private ObservableCollection<SongPlayed> allFavoriteSongs;
        #endregion

        #region 私有方法
        private SongPlayed FindSongPlayed(Song song)
        {
            //if (allFavoriteSongs.Count == 0) return null;
            var sp = from a in allFavoriteSongs where a.Song.Path == song.Path select a;
            if (sp.Count() == 0)
                return null;
            else
                return sp.First();
        }

        private class DistinctStars : IEqualityComparer<Song>
        {

            public bool Equals(Song x, Song y)
            {
                if (x.Star == y.Star)
                    return true;
                else
                    return false;
            }

            public int GetHashCode(Song obj)
            {
                return obj.GetHashCode();
            }
        }
        #endregion
    }

    public class SongPlayed
    {
        public int Frequency { get; set; }

        public Song Song { get; set; }
    }
}
